package com.atguigu.day03;

/**
 * @ClassName ReadWriteLockDemo
 * @Description 此类描述:
 * @Author dangchen
 * @DateTime 2022-09-08 18:51
 * @Version 1.0
 */

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 *读写锁
 * 对于同一个资源,我们设计多线程的操作,有读有写,交替进行.
 * 为了保证读写的数据一致性,写的时候需要独占排它,
 * 但读的时候希望高并发同时进行,可以共享,可以多个线程同时操作进行中...
 * (读也要加锁,不然在没写完的时候可能就会读取到数据)
 *
 * 题目:10个线程读,10个线程写,操作同一个资源
 *
 * 1.不加锁  不可以,写的时候原子性(同一个线程开始写和结束写之间不能被插队)被破坏
 * 2.加ReentrantLock锁 写控制了,但是读没有并发读,并发性能不好
 * 3.加读写锁  规范写入,写唯一,读并发
 *
 */

class MyCache{//资源类
    /*
    1.不加锁
    private Map<String,String> map = new HashMap<>();
    public void write(String key,String value){
        System.out.println( Thread.currentThread().getName()+"开始写入数据...");
        map.put(key,value);
        System.out.println( Thread.currentThread().getName()+"写入数据结束...");
    }

    public void read(String key){
        System.out.println( Thread.currentThread().getName()+"开始读取数据....");
        String value =  map.get(key);
        System.out.println( Thread.currentThread().getName()+"读取数据结束 value =" + value);
    }*/

    /*//2.加ReentrantLock锁
    private Map<String,String> map = new HashMap<>();
    private Lock lock =  new ReentrantLock();

    public void write(String key,String value){
        lock.lock();
        try {
            System.out.println( Thread.currentThread().getName()+"开始写入数据...");
            map.put(key,value);
            System.out.println( Thread.currentThread().getName()+"写入数据结束...");
        }finally {
            lock.unlock();
        }
    }

    public void read(String key){
        lock.lock();
        try {
            System.out.println( Thread.currentThread().getName()+"开始读取数据....");
            String value =  map.get(key);
            System.out.println( Thread.currentThread().getName()+"读取数据结束 value =" + value);
        }finally {
            lock.unlock();
        }
    }*/

    //3.加读写锁
    private Map<String,String> map = new HashMap<>();
    private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

    public void write(String key,String value){
        rwLock.writeLock().lock();
        try {
            System.out.println( Thread.currentThread().getName()+"开始写入数据...");
            map.put(key,value);
            System.out.println( Thread.currentThread().getName()+"写入数据结束...");
        }finally {
            rwLock.writeLock().unlock();
        }
    }

    public void read(String key){
        rwLock.readLock().lock();
        try {
            System.out.println( Thread.currentThread().getName()+"开始读取数据....");
            String value =  map.get(key);
            System.out.println( Thread.currentThread().getName()+"读取数据结束 value =" + value);
        }finally {
            rwLock.readLock().unlock();
        }
    }
}
public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCache myCache = new MyCache();
        for (int i = 1; i <= 10 ; i++) {
            int finalI = i;
            new Thread(() -> {
                myCache.write(finalI +"", finalI +"");
            },String.valueOf(i)).start();
        }

        for (int i = 1; i <= 10 ; i++) {
            int finalI = i;
            new Thread(() -> {
                myCache.read(finalI +"");
            },String.valueOf(i)).start();
        }
    }
}
